#ifndef __M_FORMAT_M__
#define __M_FORMAT_M__
#include "level.hpp"
#include "util.hpp"
#include "message.hpp"
#include <memory>
#include <ctime>
#include <vector>
#include <sstream>
#include <cassert>
namespace log
{
    //抽象格式化子项基类
    class FormatItem
    {   
        public:
        using ptr = std::shared_ptr<FormatItem>;
        virtual void format(std::ostream& out,const LogMsg& msg) =0;
    };

    class MsgFormatItem : public FormatItem
    {
        public:
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << msg._payload;
        }
    };

    class LineFormatItem : public FormatItem
    {
        public:
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << msg._line;
        }
    };

    class FileFormatItem : public FormatItem
    {
        public:
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << msg._file;
        }
    };

    class LevelFormatItem : public FormatItem
    {
        public:
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << LogLevel::tostring(msg._level);
        }
    };

    class TimeFormatItem : public FormatItem
    {
        public:
        TimeFormatItem(const std::string& fmt = "%H:%M:%S")
        :_time_fmt(fmt)
        {
            ;
        }
        void format(std::ostream& out,const LogMsg& msg) override
        {
            struct tm t;
            char buffer[32] = {0};
            localtime_r(&msg._ctime,&t);
            
            strftime(buffer,sizeof(buffer)-1,_time_fmt.c_str(),&t);
            out << buffer;
        }
        private: 
        std::string _time_fmt;
    };

    class LoggerFormatItem :public FormatItem
    {
        public:
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << msg._logger;
        }
    };

    class TidFormatItem : public FormatItem
    {
        public:
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << msg._tid;
        }
    };

    class OtherFormatItem : public FormatItem
    {
        public:
        OtherFormatItem(const std::string& str)
        :_str(str)
        {
            ;
        }
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << _str;
        }
        private:
        std::string _str;
    };

    class NLineFormatItem :public FormatItem
    {
        public:
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << "\n";
        }
    };

    class TableFormatItem : public FormatItem
    {
        public:
        void format(std::ostream& out,const LogMsg& msg) override
        {
            out << "\t";
        }
    };
    
    class Formatter //生成格式化字符串
    {
        /*
            %d 表示日期，包含子格式 {%H:%M:%S}
            %t 表示线程ID
            %c 表示日志器名称
            %f 表示源码文件名
            %l 表示源码行号
            %m 表示日志信息
            %n 表示换行
            %p 表示日志级别
            %T 表示制表符缩进
        */
        public:
            using ptr = std::shared_ptr<Formatter>;
            Formatter(std::string pattren = "[%d{%H:%M:%S}][%t][%c][%f:%l][%p]%T%m%n")
            :_pattren(pattren)
            {
                assert(parsePattren());
            }

            std::string formate(const LogMsg& msg) //对msg进行格式化
            {
                std::stringstream ss;
                formate(ss,msg);
                return ss.str();
            }

            void formate(std::ostream& out,const LogMsg& msg)
            {
                for(auto& item: _items)
                {
                    item->format(out,msg);
                }
            } 
            bool parsePattren()
            {
                std::vector<std::pair<std::string,std::string>> fmt_order;
                int pos=0;
                std::string key,val;
                while(pos < _pattren.size())
                {
                    //1. 处理原始字符串--判断是否为%,不是就是原始字符

                    if(_pattren[pos] != '%')
                    {
                        val += _pattren[pos++];
                        continue;
                    }

                    if(pos +1 < _pattren.size() && _pattren[pos+1] == '%')
                    {
                        val += '%';
                        pos+=2;
                        continue;
                    }
                    //原始字符的处理
                    //_items.push_back(CreateItem(nullptr,val));
                    if(val.empty() == false) fmt_order.push_back(std::make_pair("",val));
                    val.clear();

                    //格式符字符串的处理
                    if(pos == _pattren.size())
                    {
                        std::cout << "%以后没有格式化字符串" <<std::endl;
                        return false;
                    }
                    key = _pattren[pos+1];
                    pos+=2;

                    if(pos < _pattren.size() && _pattren[pos] == '{')
                    {
                        ++pos;
                        while(pos < _pattren.size() && _pattren[pos] != '}')
                        {
                            val += _pattren[pos++];
                        }

                        if(pos == _pattren.size()) 
                        {
                            std::cout << "子规则{}匹配错误" << std::endl;
                            return false;
                        }
                        ++pos;
                    }

                    fmt_order.push_back(std::make_pair(key,val));
                    val.clear();
                    key.clear();
                }

                for(auto& it: fmt_order)
                {
                    _items.push_back(CreateItem(it.first,it.second));
                }
                return true;
            }
        private:
            //根据不同的格式化字符创建不同的格式化子项对象
            FormatItem::ptr CreateItem(const std::string& key,const std::string& val)
            {     
                if(key == "d") return std::make_shared<TimeFormatItem>(val); 
                if(key == "t") return std::make_shared<TidFormatItem>();  
                if(key == "c") return std::make_shared<LoggerFormatItem>(); 
                if(key == "f") return std::make_shared<FileFormatItem>();
                if(key == "l") return std::make_shared<LineFormatItem>();
                if(key == "m") return std::make_shared<MsgFormatItem>();
                if(key == "n") return std::make_shared<NLineFormatItem>();
                if(key == "p") return std::make_shared<LevelFormatItem>();
                if(key == "c") return std::make_shared<LoggerFormatItem>();
                if(key == "T") return std::make_shared<TableFormatItem>();
                if(key.empty()) return std::make_shared<OtherFormatItem>(val);
                std::cout << "没有对应的%" << key << "格式符"<< std::endl;
                abort();

                return nullptr;
            }
            std::string _pattren; //格式化规则字符串
            std::vector<FormatItem::ptr> _items;
    };
}
#endif